local desc_draft = [[
  # 征召模式简介

  ---

  ## 身份说明

  游戏由5~10名玩家进行，身份分配和一般身份局一样，9人时增加一名内奸，10人时增加一名忠臣。

  两名内奸属不同阵营

  ---

  ## 禁用流程

  身份发放完成后，将池等分成数等份，每名玩家各观看其中一份，从中选出至多一名武将禁用（若为内奸，则至多两名）。

  ---
  
  ## 后置位补偿

  6、7号位的角色初始手牌数+1；8、9号位的角色初始手牌数+2；10号位的角色初始手牌数+3。

]]

-- 准备多个角色的武将/性别/势力（会判断隐匿）
---@param players table<ServerPlayer> @ 需要准备的角色表
---@param generals table<string> @ 角色表对应的主将武将表
---@param deputys table<string> @ 角色表对应的副将武将表
local prepareHiddenGeneral = function (players, generals, deputys)
  local room = players[1].room
  for i, player in ipairs(players) do
    local general = generals[i]
    local deputy = deputys[i]
    player.general = general
    local skills = Fk.generals[general]:getSkillNameList()
    if Fk.generals[deputy] then
      player.deputyGeneral = deputy
      table.insertTable(skills, Fk.generals[deputy]:getSkillNameList())
    end
    if table.find(skills, function (s) return Fk.skills[s].isHiddenSkill end) then
      room:setPlayerMark(player, "__hidden_general", general)
      if Fk.generals[deputy] then
        room:setPlayerMark(player, "__hidden_deputy", deputy)
        player.deputyGeneral = ""
      end
      player.general = "hiddenone"
    end
    player.gender = Fk.generals[player.general].gender
    player.kingdom = Fk.generals[player.general].kingdom
  end
  room:askForChooseKingdom(players)
  for _, player in ipairs(players) do
    room:broadcastProperty(player, "gender")
    room:broadcastProperty(player, "deputyGeneral")
    room:broadcastProperty(player, "general")
    room:broadcastProperty(player, "kingdom")
  end
end

--- getGeneralsByKingdom
--- @param room Room
--- @return table
local function getGeneralsByKingdom(room)
  local general_pile = room.general_pile
  local kingdom_map = {}
  for i = 1, #general_pile do
    local gname = general_pile[i]
    local general = Fk.generals[gname]
    if general then
      local kingdom = general.kingdom
      if not kingdom_map[kingdom] then
        kingdom_map[kingdom] = {}
      end
      table.insert(kingdom_map[kingdom], gname)
    end
  end
  return kingdom_map
end

--- banGeneral
--- @param room Room
--- @param gname string
local function banGeneral(room, gname)
  local banned_generals = room:getBanner("@&banned_generals") or {}
  room:findGeneral(gname)
  table.insert(banned_generals, gname)
  room:setBanner("@&banned_generals", banned_generals)
end

--- do draft
---@param room Room
local function doDraft(room)
  -- local kingdom_map = getGeneralsByKingdom(room)
  local all_generals = table.simpleClone(room.general_pile)
  table.shuffle(all_generals)
  local players = room.players
  local viewNum = #all_generals // #players
  local req = Request:new(players, "CustomDialog")
  req.focus_text = "draft_rule"
  for j, p in ipairs(players) do
    local i = j-1
    local isRenegade = p.role:endsWith("renegade")
    local request_data = {
      path = "packages/aaa_fenghou/qml/BanGenerals.qml",
      data = { table.slice(all_generals, i*viewNum+1, j*viewNum), {"#ReadyBan"}, 0, isRenegade and 2 or 1 }
    }
    req:setData(p, request_data)
    req:setDefaultReply(p, {cards = {}})
  end

  local toBan = {}
  for _, p in ipairs(players) do
    local selected = req:getResult(p)
    table.insertTableIfNeed(toBan, selected.cards)
  end
  table.shuffle(toBan)
  table.forEach(toBan, function(p) banGeneral(room, p) end)
end

local draft_getLogic = function()
  ---@class draft_logic : GameLogic
  local draft_logic = GameLogic:subclass("draft_logic")

  function draft_logic:initialize(room)
    GameLogic.initialize(self, room)
    self.role_table = {nil, nil, nil, nil,
    { "lord", "rebel", "renegade", "rebel", "loyalist" },
    { "lord", "rebel", "renegade", "rebel", "loyalist", "rebel" },
    { "lord", "rebel", "renegade", "rebel", "loyalist", "rebel", "loyalist" },
    { "lord", "rebel", "renegade", "rebel", "loyalist", "rebel", "loyalist", "rebel" },
    { "lord", "rebel", "renegade", "rebel", "loyalist", "rebel", "loyalist", "rebel", "gama__renegade" },
    { "lord", "rebel", "renegade", "rebel", "loyalist", "rebel", "loyalist", "rebel", "gama__renegade", "delta__renegade" },
  }
  end

  function draft_logic:chooseGenerals()
    local room = self.room
    local generalNum = room.settings.generalNum
    local n = room.settings.enableDeputy and 2 or 1
    local lord = room:getLord()

    if lord == nil then return end
    room.current = lord
    doDraft(room)
    local generals = room:findGenerals(function(g) return table.contains(Fk.lords, g) end, generalNum//2)
    table.insertTable(generals, room:getNGenerals(generalNum))
    local lord_generals = room:askForGeneral(lord, generals, n)
    local lord_general, deputy
    if type(lord_generals) == "table" then
      deputy = lord_generals[2]
      lord_general = lord_generals[1]
    else
      lord_general = lord_generals
      lord_generals = {lord_general}
    end

    local ret_generals = table.filter(generals, function(g) return not table.contains(lord_generals, g) end)
    room:returnToGeneralPile(ret_generals)

    prepareHiddenGeneral({lord}, {lord_general}, {deputy})
    room:prepareGeneral(lord, lord_general, deputy)
    room:askForChooseKingdom({lord})

    -- 显示技能
    local canAttachSkill = function(player, skillName)
      local skill = Fk.skills[skillName]
      if not skill then
        fk.qCritical("Skill: "..skillName.." doesn't exist!")
        return false
      end
      if #skill.attachedKingdom > 0 and not table.contains(skill.attachedKingdom, player.kingdom) then
        return false
      end
      return true
    end

    local lord_skills = {}
    local lord_gs = Fk.generals[lord_general]
    for _, s in ipairs(lord_gs:getSkillNameList()) do
      if canAttachSkill(lord, s) then
        table.insertIfNeed(lord_skills, s)
      end
    end
    local deputyGeneral = Fk.generals[lord.deputyGeneral]
    if deputyGeneral then
      for _, s in ipairs(deputyGeneral:getSkillNameList()) do
        if canAttachSkill(lord, s) then
          table.insertIfNeed(lord_skills, s)
        end
      end
    end
    for _, skill in ipairs(lord_skills) do
      room:doBroadcastNotify("AddSkill", json.encode{ lord.id, skill })
    end

    local nonlord = room:getOtherPlayers(lord, true)
    local nonlord_generals = table.random(room.general_pile, #nonlord * generalNum)
    if type(nonlord_generals) == "string" then nonlord_generals = {nonlord_generals} end
    local req = Request:new(nonlord, "AskForGeneral")
    req.focus_text = "AskForGeneral"
    for i, p in ipairs(nonlord) do
      local arg = table.slice(nonlord_generals, (i - 1) * generalNum + 1, i * generalNum + 1)
      req:setData(p, {arg, n})
      req:setDefaultReply(p, table.random(arg, n))
    end

    for _, p in ipairs(nonlord) do
      local general, deputy_general = table.unpack(req:getResult(p))
      room:findGeneral(general)
      room:findGeneral(deputy_general)
      room:prepareGeneral(p, general, deputy_general)
    end

    room:askForChooseKingdom(nonlord)
  end

  return draft_logic
end

local draft_rule = fk.CreateTriggerSkill{
  name = "#draft_rule",
  mute = true,
  priority = 0.001,
  events = {fk.DrawInitialCards},
  can_trigger = function(self, event, target, player, data)
    return target == player and not (event == fk.Deathed and player.rest > 0)
  end,
  on_cost = Util.TrueFunc,
  on_use = function(self, event, target, player, data)
    if event == fk.DrawInitialCards then
      local plus = (player.seat - 4) // 2
      if plus > 0 then
        data.num = data.num + plus
      end
    end
  end,
}
Fk:addSkill(draft_rule)

local draft = fk.CreateGameMode{
  name = "draft",
  minPlayer = 5,
  maxPlayer = 10,
  logic = draft_getLogic,
  rule = draft_rule,
  main_mode = "aaa_role_mode",
  winner_getter = function(self, victim)
    if not victim.surrendered and victim.rest > 0 then
      return ""
    end
    local room = victim.room
    local role_map = { ["lord"] = 0, ["loyalist"] = 0, ["rebel"] = 0, ["renegade"] = 0, }

    for _, p in ipairs(room.players) do
      if not p.surrendered and not (p.dead and p.rest == 0) then
        local role = string.endsWith(p.role, "renegade") and "renegade" or p.role
        role_map[role] = role_map[role] + 1
      end
    end

    local winner = ""
    if role_map["lord"] == 0 then-- 主公死亡
      if role_map["loyalist"] > 0 or role_map["rebel"] > 0 or role_map["renegade"] > 1 then  -- 忠臣/反贼存活；或者多个内奸存活
        winner = "rebel"
      elseif role_map["renegade"] == 1 then -- 只有一个内奸存活
        for _, p in ipairs(room.players) do
          if not p.surrendered and not (p.dead and p.rest == 0) and string.endsWith(p.role, "renegade") then
            winner = p.role
          end
        end
      else
        return ""
      end
    else -- 主公存活
      if role_map["rebel"] == 0 and role_map["renegade"] == 0 then -- 反贼、内奸死亡
        winner = "lord+loyalist"
      else
        return ""
      end
    end

    return winner
  end,
  surrender_func = function(self, playedTime)
    local roleCheck = false
    local roleText = ""
    local roleTable = {nil, nil, nil, nil,
    { "lord", "rebel", "renegade", "rebel", "loyalist" },
    { "lord", "rebel", "renegade", "rebel", "loyalist", "rebel" },
    { "lord", "rebel", "renegade", "rebel", "loyalist", "rebel", "loyalist" },
    { "lord", "rebel", "renegade", "rebel", "loyalist", "rebel", "loyalist", "rebel" },
    { "lord", "rebel", "renegade", "rebel", "loyalist", "rebel", "loyalist", "rebel", "gama__renegade" },
    { "lord", "rebel", "renegade", "rebel", "loyalist", "rebel", "loyalist", "rebel", "gama__renegade", "delta__renegade" },
  }

    local room = Fk:currentRoom()
    local rolesOnfield = table.simpleClone(roleTable[#room.players])

    for _, p in ipairs(room.players) do
      if p.dead then
        table.removeOne(rolesOnfield, p.role)
      end
    end

    local role_map = {
      ["lord"] = #table.filter(rolesOnfield, function(r) return r == "lord" end),
      ["loyalist"] = #table.filter(rolesOnfield, function(r) return r == "loyalist" end),
      ["rebel"] = #table.filter(rolesOnfield, function(r) return r == "rebel" end),
      ["renegade"] = #table.filter(rolesOnfield, function(r) return string.endsWith(r, "renegade") end),
    }

    if string.endsWith(Self.role, "renegade") then
      local rebelNum = role_map["rebel"]
      local renegadeNum = role_map["renegade"]
      roleCheck = (rebelNum == 0) and (renegadeNum == 1)
      roleText = "left lord and loyalist alive"

    elseif Self.role == "rebel" then
      local rebelNum = role_map["rebel"]
      local renegadeNum = role_map["renegade"]
      roleCheck = (renegadeNum == 0) and (rebelNum == 1)
      roleText = "left one rebel alive"
    elseif Self.role == "loyalist" then
        return { { text = "loyalist never surrender", passed = false } }
    else
      local loyalistNum = role_map["loyalist"]
      local rebelNum = role_map["rebel"]
      local renegadeNum = role_map["renegade"]

      if rebelNum > 0 then -- 1+ rebel, no loyalist, no renegade, no wild
        roleCheck = (renegadeNum == 0) and (loyalistNum == 0)
      else -- no rebel, no loyalist, 1 renegade or 1 wild
        roleCheck = (renegadeNum == 0) and (renegadeNum == 0)
      end

      roleText = "left you alive"
    end

    return {
      { text = roleText, passed = roleCheck },
    }
  end,
  get_adjusted = function(self, player)
    return Fk.game_modes["aaa_role_mode"].getAdjustedProperty(self, player)
  end
}

Fk:loadTranslationTable{
  ["draft"] = "征召模式",
  [":draft"] = desc_draft,
  ["draft_rule"] = "征召规则",
  ["#ReadyBan"] = "确定禁用",
  ["#BanGenerals"] = "禁用武将",
  ["$DraftBanGenerals"] = "选择最多%arg名武将禁用",
  ["@&banned_generals"] = "本局禁用武将",
  ["beta__renegade"] = "内奸",
  ["gama__renegade"] = "内奸",
  ["delta__renegade"] = "内奸",
}

return draft
